/*
 * @author ${user}
 * @date ${year}-${month}-${day}
 */
package net.xdclass.aspect;

import groovyjarjarpicocli.CommandLine;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.annotation.RepeatSubmit;
import net.xdclass.interceptor.LoginInterceptor;
import net.xdclass.util.CommonUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.bouncycastle.asn1.ocsp.Signature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class RepeatSubmitAspect {
	@Autowired
	private StringRedisTemplate redisTemplate;

	@Autowired
	private RedissonClient redissonClient;

	@Pointcut("@annotation(repeatSubmit)")
	public void pointCutNoRepeatSubmit(RepeatSubmit repeatSubmit){}

    @Around("pointCutNoRepeatSubmit(repeatSubmit)")
	public Object around(ProceedingJoinPoint joinPoint, RepeatSubmit repeatSubmit) throws Throwable {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		long lockTime = repeatSubmit.lockTime();
		long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
		boolean res = false;
		String type = repeatSubmit.limitType().name();
		if(type.equalsIgnoreCase(RepeatSubmit.Type.PARAM.name())){
			MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
	        Method method = methodSignature.getMethod();
	        String classname = method.getDeclaringClass().getName();
	        String ipAddr = CommonUtil.getIpAddr(request);
	        String key = "order-server:repeat_submit:" + CommonUtil.MD5(String.format("%s-%s-%s-%s",classname,method,ipAddr,accountNo));
			RLock lock = redissonClient.getLock(key);
			res = lock.tryLock(0,lockTime,TimeUnit.SECONDS);
		}else{
			String key = request.getHeader("token_header");
			res = redisTemplate.delete(key);
		}
		if(!res){
          log.error("请求重复提交");
          return null;
		}
        log.info("环绕执行前");
		Object obj = joinPoint.proceed();
		log.info("环绕执行后");
        return  obj;
	}
}
